﻿using System;
using System.Collections;
using System.Collections.Generic;
using GDGeek;
using MrPP.Myth;
using UnityEngine;
using Mirror;
using static MrPP.SerriedCabinet.CabinetGroup;
using MrPP.Restful;

namespace MrPP.SerriedCabinet
{
    public interface ICheckReceiver {


        int getTab();
        int getPage();
        CheckPost.State getState();
        ItemData[] getItems();

        int getWaitPage();
        int getCheckPage();
        int getOtherPage();

        List<string> getCheckList();





    }
    public partial class CheckReceiver : NetworkBehaviour, IBridgeReceiver, ICheckReceiver
    {

        private static CheckReceiver Instance_;
        public static CheckReceiver Instance
        {
            get
            {
                return Instance_;
            }
        }




     //   [SerializeField]
       // private CheckModel _model;

        [SerializeField]
        private List<CheckViewAbstract> _callback = new List<CheckViewAbstract>();

      //  CheckViewAbstract


        [SyncVar(hook ="onTab")]
        [SerializeField]
        private int tab_ = 0;

        public int tab {
            set {
                if (this.isClient)
                {  
                    Bridge.Instance.post(this.longName(), "tab", value);
                }
            }
            get {
                return tab_;
            }
        }



        private void onTab(int oldValue, int newValue) {
            _callback.ForEach(item => item.onTab(oldValue, newValue));
        }


       //==========================


        [SyncVar(hook ="onState")]
        [SerializeField]
        private CheckPost.State state_ = CheckPost.State.Close;



        private void onState(CheckPost.State oldValue, CheckPost.State newValue)
        {
            _callback.ForEach(item => item.onState(oldValue, newValue));
        }

        public CheckPost.State state {
            get {
                return state_;
            }
            set {
                Bridge.Instance.post(this.longName(), "state", (int)value);
            }
        }

        internal void loading()
        {
            Bridge.Instance.post(this.longName(), "loading");
        }

        
        public class ItemList : SyncList<ItemData> { }
        public ItemList _items = new ItemList();

        internal void addCheck(string key)
        {
            Bridge.Instance.post(this.longName(), "check", key);
        }

        [SyncVar(hook ="onWaitPage")]
        [SerializeField]
        private int _waitPage = 0;

        private void onWaitPage(int oldValue, int newValue)
        {
         //   var old = _waitPage;
           // _waitPage = val;
          //  _model.onWaitPage?.Invoke(old, _waitPage);

            _callback.ForEach(item => item.onWaitPage(oldValue, newValue));
        }

        public int waitPage
        {
            get
            {
                return _waitPage;
            }
            set
            {
                Bridge.Instance.post(this.longName(), "waitPage", value);
            }
        }



        [SyncVar(hook = "onCheckPage")]
        [SerializeField]
        private int _checkPage = 0;

        private void onCheckPage(int oldValue, int newValue)
        {
          //  var old = _checkPage;
            //_checkPage = val;
           // _model.onCheckPage?.Invoke(old, _checkPage);

            _callback.ForEach(item => item.onCheckPage(oldValue, newValue));
        }


        public int checkPage
        {
            get
            {
                return _checkPage;
            }
            set
            {
                Bridge.Instance.post(this.longName(), "checkPage", value);
            }
        }




        [SyncVar(hook = "onOtherPage")]
        [SerializeField]
        private int _otherPage = 0;

        private void onOtherPage(int oldValue, int newValue)
        {
          //  var old = _otherPage;
           // _otherPage = val;
           // _model.onOtherPage?.Invoke(old, _otherPage);
            _callback.ForEach(item => item.onOtherPage(oldValue, newValue));
        }


        public int otherPage
        {
            get
            {
                return _otherPage;
            }
            set
            {
                Bridge.Instance.post(this.longName(), "otherPage", value);
            }
        }


        private SyncListString  _list = new SyncListString();

        public string handle => this.longName();

        public int getTab()
        {
            return tab;
        }

        public int getPage()
        {
            throw new NotImplementedException();
        }

        public CheckPost.State getState()
        {
            return state;
        }

        public ItemData[] getItems()
        {
            ItemData[] ret = new ItemData[_items.Count];
            _items.CopyTo(ret, 0);
            return ret;
        }

        public int getWaitPage()
        {
            return _waitPage;
        }

        public int getCheckPage()
        {
            return _checkPage;
        }

        public int getOtherPage()
        {
            return _otherPage;
        }

        public List<string> getCheckList()
        {
            string[] ret = new string[_list.Count];
            _list.CopyTo(ret, 0);
            return new List<string>(ret);

        }
        // Start is called before the first frame update
        void Awake()
        {
            Instance_ = this;
            BridgeBroadcast.Instance.addReceiver(this);

       

            this._callback.ForEach(item => item.setReceiver(this));

            _items.Callback += onItemData;
            _list.Callback += onCheck;
        }
        void OnDestroy() {
            if (BridgeBroadcast.IsInitialized) { 
                BridgeBroadcast.Instance.removeReceiver(this);
            }
        }
        private ListUpdate _checkUpdate = null;

        [SerializeField]
        private AudioSource _audio;
        [SerializeField]
        private AudioClip _addClip;
        void onCheck(SyncList<string>.Operation op, int index, string oldItem, string newItem)
        {

            if (op == SyncList<string>.Operation.OP_ADD) {
                _audio.PlayOneShot(_addClip);
            }
            if (_checkUpdate == null)
            {
                _checkUpdate = new ListUpdate(delegate {

                    string[] ret = new string[_list.Count];
                    _list.CopyTo(ret, 0);
                    _callback.ForEach(item => item.onCheckList(new List<string>(ret)));
                });
            }
            _checkUpdate._begin = 0.0f;


            
        }
        private ListUpdate _listUpdate = null;
        void Update() {
            if (_listUpdate != null) {
                _listUpdate._begin += Time.deltaTime;
                if (_listUpdate._begin > _listUpdate._time) {
                    _listUpdate._action?.Invoke();
                    _listUpdate = null;
                }
            }
            if (_checkUpdate != null)
            {
                _checkUpdate._begin += Time.deltaTime;
                if (_checkUpdate._begin > _checkUpdate._time)
                {
                    _checkUpdate._action?.Invoke();
                    _checkUpdate = null;
                }
            }
            
        }

        void onItemData(SyncList<ItemData>.Operation op, int index, ItemData oldItem, ItemData newItem)
        {
            if (_listUpdate == null) {
                _listUpdate = new ListUpdate(delegate {
                    ItemData[] ret = new ItemData[_items.Count];
                    _items.CopyTo(ret, 0);
                    _callback.ForEach(item => item.onItems(ret));
                });
            }
            _listUpdate._begin = 0.0f;
           
        }
      
        public void broadcast(string evt, object data)
        {
            switch (evt) {
                case "tab":
                    this.tab_ = (int)(data);
                    break;
                case "state":
                    this.state_ = (CheckPost.State)(int)(data);
                    break;
                case "waitPage":
                    this._waitPage = (int)(data);
                    break;
                case "checkPage":
                    this._checkPage = (int)(data);
                    break;
                case "otherPage":
                    this._otherPage = (int)(data);
                    break;
                case "archive":
                   // this._archives.Add((ArchivesData)(data));
                    this._items.Add(CabinetGroup.Instance.getItem((ArchivesData)(data)));
                    break;
                case "check":
                    this._list.Add((string)(data));
                    break;
                case "loading":
                    this.doLoading();
                    break;

            }
        }

        public void loading(ItemData[] items)
        {
            _items.Clear();

            foreach (var item in items)
            {
                _items.Add(item);
            }
            _list.Clear();
            state = CheckPost.State.Running;
        }
        public void doLoading()
        {
            string uri = Restful.RestfulManager.Uri(UriManager.GetOrCreateInstance.getUri("api").value, "check");
           // doLoding(uri);
          
            var op = Restful.RestfulManager.Instance.options(uri);

            state = CheckPost.State.Loading;
            Restful.RestfulManager.Instance.getArray<ArchivesData>(op, delegate(ArchivesData[] datas)
            {
                List<ItemData> list = new List<ItemData>();
               
             
               // _items.Clear();
                foreach (var data in datas)
                {
                    list.Add(CabinetGroup.Instance.getItem(data));
                  //  _items.Add(CabinetGroup.Instance.getItem(data));
                }
                loading(list.ToArray());  

                 // state = CheckPost.State.Running;
            });
        }

       
    }
}